{ "cells": [ { "cell_type": "markdown", "metadata": { "school_cell_uuid": "6b664ac5e2c6492aa0e3f5cbd9bd25cf" }, "source": [ "# 4.6 데이터프레임 합성" ] }, { "cell_type": "markdown", "metadata": { "school_cell_uuid": "4d3579de59f54ae6af27431a03eb32cd" }, "source": [ "판다스는 두 개 이상의 데이터프레임을 하나로 합치는 데이터 병합(merge)이나 연결(concatenate)을 지원한다." ] }, { "cell_type": "markdown", "metadata": { "school_cell_uuid": "b41585414225461aa48873974dab9ff4" }, "source": [ "## `merge` 함수를 사용한 데이터프레임 병합" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "```{margin}\n", "`merge`\n", "```" ] }, { "cell_type": "markdown", "metadata": { "school_cell_uuid": "c61603512a064b10b418508bd086c467" }, "source": [ "`merge` 함수는 두 데이터 프레임의 공통 열 혹은 인덱스를 기준으로 두 개의 테이블을 합친다. 이 때 기준이 되는 열, 행의 데이터를 키(key)라고 한다." ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "school_cell_uuid": "ca995b1dc8314531802808260235aa48" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
고객번호이름
01001둘리
11002도우너
21003또치
31004길동
41005희동
51006마이콜
61007영희
\n", "
" ], "text/plain": [ " 고객번호 이름\n", "0 1001 둘리\n", "1 1002 도우너\n", "2 1003 또치\n", "3 1004 길동\n", "4 1005 희동\n", "5 1006 마이콜\n", "6 1007 영희" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df1 = pd.DataFrame({\n", " '고객번호': [1001, 1002, 1003, 1004, 1005, 1006, 1007],\n", " '이름': ['둘리', '도우너', '또치', '길동', '희동', '마이콜', '영희']\n", "}, columns=['고객번호', '이름'])\n", "df1" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "school_cell_uuid": "7b868901382c4405954d1c67d34b8eb8" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
고객번호금액
0100110000
1100120000
2100515000
310065000
41008100000
5100130000
\n", "
" ], "text/plain": [ " 고객번호 금액\n", "0 1001 10000\n", "1 1001 20000\n", "2 1005 15000\n", "3 1006 5000\n", "4 1008 100000\n", "5 1001 30000" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df2 = pd.DataFrame({\n", " '고객번호': [1001, 1001, 1005, 1006, 1008, 1001],\n", " '금액': [10000, 20000, 15000, 5000, 100000, 30000]\n", "}, columns=['고객번호', '금액'])\n", "df2" ] }, { "cell_type": "markdown", "metadata": { "school_cell_uuid": "433dd514e3484b7b99ac1f0d5602cb56" }, "source": [ "`merge` 함수로 위의 두 데이터프레임 df1, df2 를 합치면 공통 열인 `고객번호` 열을 기준으로 데이터를 찾아서 합친다. 이 때 기본적으로는 양쪽 데이터프레임에 모두 키가 존재하는 데이터만 보여주는 inner join 방식을 사용한다." ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "school_cell_uuid": "65b0323d90f0430e9edd8ea43529cb03" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
고객번호이름금액
01001둘리10000
11001둘리20000
21001둘리30000
31005희동15000
41006마이콜5000
\n", "
" ], "text/plain": [ " 고객번호 이름 금액\n", "0 1001 둘리 10000\n", "1 1001 둘리 20000\n", "2 1001 둘리 30000\n", "3 1005 희동 15000\n", "4 1006 마이콜 5000" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pd.merge(df1, df2)" ] }, { "cell_type": "markdown", "metadata": { "school_cell_uuid": "9fffca783ba54a7e9df1a7f776e5ff4a" }, "source": [ "outer join 방식은 키 값이 한쪽에만 있어도 데이터를 보여준다." ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "school_cell_uuid": "a5e9de8a231f47629d7847a48f9d59a9" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
고객번호이름금액
01001둘리10000.0
11001둘리20000.0
21001둘리30000.0
31002도우너NaN
41003또치NaN
51004길동NaN
61005희동15000.0
71006마이콜5000.0
81007영희NaN
91008NaN100000.0
\n", "
" ], "text/plain": [ " 고객번호 이름 금액\n", "0 1001 둘리 10000.0\n", "1 1001 둘리 20000.0\n", "2 1001 둘리 30000.0\n", "3 1002 도우너 NaN\n", "4 1003 또치 NaN\n", "5 1004 길동 NaN\n", "6 1005 희동 15000.0\n", "7 1006 마이콜 5000.0\n", "8 1007 영희 NaN\n", "9 1008 NaN 100000.0" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pd.merge(df1, df2, how='outer')" ] }, { "cell_type": "markdown", "metadata": { "school_cell_uuid": "8561fb8d59014b65b53338fa62e2cf5b" }, "source": [ "left, right 방식은 각각 첫번째, 혹은 두번째 데이터프레임의 키 값을 모두 보여준다." ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "school_cell_uuid": "57296be296e74e20a3af293684c7b5e6" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
고객번호이름금액
01001둘리10000.0
11001둘리20000.0
21001둘리30000.0
31002도우너NaN
41003또치NaN
51004길동NaN
61005희동15000.0
71006마이콜5000.0
81007영희NaN
\n", "
" ], "text/plain": [ " 고객번호 이름 금액\n", "0 1001 둘리 10000.0\n", "1 1001 둘리 20000.0\n", "2 1001 둘리 30000.0\n", "3 1002 도우너 NaN\n", "4 1003 또치 NaN\n", "5 1004 길동 NaN\n", "6 1005 희동 15000.0\n", "7 1006 마이콜 5000.0\n", "8 1007 영희 NaN" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pd.merge(df1, df2, how='left')" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "school_cell_uuid": "767dee654c874038baf59e4f7cb3b51f" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
고객번호이름금액
01001둘리10000
11001둘리20000
21001둘리30000
31005희동15000
41006마이콜5000
51008NaN100000
\n", "
" ], "text/plain": [ " 고객번호 이름 금액\n", "0 1001 둘리 10000\n", "1 1001 둘리 20000\n", "2 1001 둘리 30000\n", "3 1005 희동 15000\n", "4 1006 마이콜 5000\n", "5 1008 NaN 100000" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pd.merge(df1, df2, how='right')" ] }, { "cell_type": "markdown", "metadata": { "school_cell_uuid": "38c341b4e3704053b8ee2046ebd9dbb9" }, "source": [ "만약 테이블에 키 값이 같은 데이터가 여러개 있는 경우에는 있을 수 있는 모든 경우의 수를 따져서 조합을 만들어 낸다." ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "school_cell_uuid": "6abf0c3733604366bc45c319cbedc72b" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
품종꽃잎길이
0setosa1.4
1setosa1.3
2virginica1.5
3virginica1.3
\n", "
" ], "text/plain": [ " 품종 꽃잎길이\n", "0 setosa 1.4\n", "1 setosa 1.3\n", "2 virginica 1.5\n", "3 virginica 1.3" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df1 = pd.DataFrame({\n", " '품종': ['setosa', 'setosa', 'virginica', 'virginica'],\n", " '꽃잎길이': [1.4, 1.3, 1.5, 1.3]},\n", " columns=['품종', '꽃잎길이'])\n", "df1" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "school_cell_uuid": "c93741632f264ff2bc19857e19f8288c" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
품종꽃잎너비
0setosa0.4
1virginica0.3
2virginica0.5
3versicolor0.3
\n", "
" ], "text/plain": [ " 품종 꽃잎너비\n", "0 setosa 0.4\n", "1 virginica 0.3\n", "2 virginica 0.5\n", "3 versicolor 0.3" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df2 = pd.DataFrame({\n", " '품종': ['setosa', 'virginica', 'virginica', 'versicolor'],\n", " '꽃잎너비': [0.4, 0.3, 0.5, 0.3]},\n", " columns=['품종', '꽃잎너비'])\n", "df2" ] }, { "cell_type": "markdown", "metadata": { "school_cell_uuid": "5eb8af9497764b56b13cf9c67c24db18" }, "source": [ "이 데이터에서 키 값 setosa에 대해 왼쪽 데이터프레임는 1.4와 1.3라는 2개의 데이터, 오른쪽 데이터프레임에 0.4라는 1개의 데이터가 있으므로 병합된 데이터에는 setosa가 (1.4, 0.4), (1.3, 0.4) 두 개의 데이터가 생긴다. 키 값 virginica의 경우에는 왼쪽 데이터프레임에 1.5와 1.3라는 2개의 데이터, 오른쪽 데이터프레임에 0.3와 0.5라는 2개의 데이터가 있으므로 2개와 2개의 조합에 의해 4가지 값이 생긴다." ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "school_cell_uuid": "5e21b76a347d476eac374283a316f269" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
품종꽃잎길이꽃잎너비
0setosa1.40.4
1setosa1.30.4
2virginica1.50.3
3virginica1.50.5
4virginica1.30.3
5virginica1.30.5
\n", "
" ], "text/plain": [ " 품종 꽃잎길이 꽃잎너비\n", "0 setosa 1.4 0.4\n", "1 setosa 1.3 0.4\n", "2 virginica 1.5 0.3\n", "3 virginica 1.5 0.5\n", "4 virginica 1.3 0.3\n", "5 virginica 1.3 0.5" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pd.merge(df1, df2)" ] }, { "cell_type": "markdown", "metadata": { "school_cell_uuid": "9e429e26659a4d0b85b8143d0709b5c2" }, "source": [ "두 데이터프레임에서 이름이 같은 열은 모두 키가 된다. 만약 이름이 같아도 키가 되면 안되는 열이 있다면 `on` 인수로 기준열을 명시해야 한다. 다음 예에서 첫번째 데이터프레임의 \"데이터\"는 실제로는 금액을 나타내는 데이터이고 두번째 데이터프레임의 \"데이터\"는 실제로는 성별을 나타내는 데이터이므로 이름이 같아도 다른 데이터이다. 따라서 이 열은 기준열이 되면 안된다." ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "school_cell_uuid": "17670124b837436eaf758ee469a2afe9" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
고객명날짜데이터
0춘향2018-01-0120000
1춘향2018-01-0230000
2몽룡2018-01-01100000
\n", "
" ], "text/plain": [ " 고객명 날짜 데이터\n", "0 춘향 2018-01-01 20000\n", "1 춘향 2018-01-02 30000\n", "2 몽룡 2018-01-01 100000" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df1 = pd.DataFrame({\n", " '고객명': ['춘향', '춘향', '몽룡'],\n", " '날짜': ['2018-01-01', '2018-01-02', '2018-01-01'],\n", " '데이터': ['20000', '30000', '100000']})\n", "df1" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "school_cell_uuid": "8cbde58855f94f9c98c83a2240c6d9d4" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
고객명데이터
0춘향여자
1몽룡남자
\n", "
" ], "text/plain": [ " 고객명 데이터\n", "0 춘향 여자\n", "1 몽룡 남자" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df2 = pd.DataFrame({\n", " '고객명': ['춘향', '몽룡'],\n", " '데이터': ['여자', '남자']})\n", "df2" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "school_cell_uuid": "4084064009d04ac2addb64ef89cb3310" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
고객명날짜데이터_x데이터_y
0춘향2018-01-0120000여자
1춘향2018-01-0230000여자
2몽룡2018-01-01100000남자
\n", "
" ], "text/plain": [ " 고객명 날짜 데이터_x 데이터_y\n", "0 춘향 2018-01-01 20000 여자\n", "1 춘향 2018-01-02 30000 여자\n", "2 몽룡 2018-01-01 100000 남자" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pd.merge(df1, df2, on='고객명')" ] }, { "cell_type": "markdown", "metadata": { "school_cell_uuid": "505311f5babf4ffba7b4978fedf21a64" }, "source": [ "이 때 기준 열이 아니면서 이름이 같은 열에는 `_x` 또는 `_y` 와 같은 접미사가 붙는다." ] }, { "cell_type": "markdown", "metadata": { "school_cell_uuid": "a301562c92ae470db09c6f031fbf847b" }, "source": [ "반대로 키가 되는 기준열의 이름이 두 데이터프레임에서 다르다면 `left_on`, `right_on` 인수를 사용하여 기준열을 명시해야 한다." ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "school_cell_uuid": "7f99a2c7a1594659b4fa08dec518aaf2" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
이름성적
0영희1
1철수2
2철수3
\n", "
" ], "text/plain": [ " 이름 성적\n", "0 영희 1\n", "1 철수 2\n", "2 철수 3" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df1 = pd.DataFrame({\n", " '이름': ['영희', '철수', '철수'],\n", " '성적': [1, 2, 3]})\n", "df1" ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "school_cell_uuid": "ff87cec64cbe4948b9f8c278b5510db0" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
성명성적2
0영희4
1영희5
2철수6
\n", "
" ], "text/plain": [ " 성명 성적2\n", "0 영희 4\n", "1 영희 5\n", "2 철수 6" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df2 = pd.DataFrame({\n", " '성명': ['영희', '영희', '철수'],\n", " '성적2': [4, 5, 6]})\n", "df2" ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "school_cell_uuid": "84194614f5064491a3563b2044ce77c9" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
이름성적성명성적2
0영희1영희4
1영희1영희5
2철수2철수6
3철수3철수6
\n", "
" ], "text/plain": [ " 이름 성적 성명 성적2\n", "0 영희 1 영희 4\n", "1 영희 1 영희 5\n", "2 철수 2 철수 6\n", "3 철수 3 철수 6" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pd.merge(df1, df2, left_on='이름', right_on=\"성명\")" ] }, { "cell_type": "markdown", "metadata": { "school_cell_uuid": "1c7adc88d10c45a2b72d549a04164e80" }, "source": [ "일반 데이터 열이 아닌 인덱스를 기준열로 사용하려면 `left_index` 또는 `right_index` 인수를 `True` 로 설정한다." ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "school_cell_uuid": "ab41a24dc50e4c3fac5150a1d0f82b6d" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
도시연도인구
0서울20009853972
1서울20059762546
2서울20109631482
3부산20003655437
4부산20053512547
\n", "
" ], "text/plain": [ " 도시 연도 인구\n", "0 서울 2000 9853972\n", "1 서울 2005 9762546\n", "2 서울 2010 9631482\n", "3 부산 2000 3655437\n", "4 부산 2005 3512547" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df1 = pd.DataFrame({\n", " '도시': ['서울', '서울', '서울', '부산', '부산'],\n", " '연도': [2000, 2005, 2010, 2000, 2005],\n", " '인구': [9853972, 9762546, 9631482, 3655437, 3512547]})\n", "df1" ] }, { "cell_type": "code", "execution_count": 17, "metadata": { "school_cell_uuid": "03c8c1c3b9b24dff90ae26c4064f9d2e" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
데이터1데이터2
부산200001
200523
서울200045
200567
201089
20151011
\n", "
" ], "text/plain": [ " 데이터1 데이터2\n", "부산 2000 0 1\n", " 2005 2 3\n", "서울 2000 4 5\n", " 2005 6 7\n", " 2010 8 9\n", " 2015 10 11" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df2 = pd.DataFrame(\n", " np.arange(12).reshape((6, 2)),\n", " index=[['부산', '부산', '서울', '서울', '서울', '서울'],\n", " [2000, 2005, 2000, 2005, 2010, 2015]],\n", " columns=['데이터1', '데이터2'])\n", "df2" ] }, { "cell_type": "code", "execution_count": 18, "metadata": { "school_cell_uuid": "25ed02de1b984b9bafdd450b6f391112" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
도시연도인구데이터1데이터2
0서울2000985397245
1서울2005976254667
2서울2010963148289
3부산2000365543701
4부산2005351254723
\n", "
" ], "text/plain": [ " 도시 연도 인구 데이터1 데이터2\n", "0 서울 2000 9853972 4 5\n", "1 서울 2005 9762546 6 7\n", "2 서울 2010 9631482 8 9\n", "3 부산 2000 3655437 0 1\n", "4 부산 2005 3512547 2 3" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pd.merge(df1, df2, left_on=['도시', '연도'], right_index=True)" ] }, { "cell_type": "code", "execution_count": 19, "metadata": { "school_cell_uuid": "404694ddf9a04fe0885d1811cb803b70" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
서울부산
a1.02.0
c3.04.0
e5.06.0
\n", "
" ], "text/plain": [ " 서울 부산\n", "a 1.0 2.0\n", "c 3.0 4.0\n", "e 5.0 6.0" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df1 = pd.DataFrame(\n", " [[1., 2.], [3., 4.], [5., 6.]],\n", " index=['a', 'c', 'e'],\n", " columns=['서울', '부산'])\n", "df1" ] }, { "cell_type": "code", "execution_count": 20, "metadata": { "school_cell_uuid": "1b12fad0ec414408838c464cd706e5d3" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
대구광주
b7.08.0
c9.010.0
d11.012.0
e13.014.0
\n", "
" ], "text/plain": [ " 대구 광주\n", "b 7.0 8.0\n", "c 9.0 10.0\n", "d 11.0 12.0\n", "e 13.0 14.0" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df2 = pd.DataFrame(\n", " [[7., 8.], [9., 10.], [11., 12.], [13, 14]],\n", " index=['b', 'c', 'd', 'e'],\n", " columns=['대구', '광주'])\n", "df2" ] }, { "cell_type": "code", "execution_count": 21, "metadata": { "school_cell_uuid": "b046e6a685374379a755253cc164d7cd" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
서울부산대구광주
a1.02.0NaNNaN
bNaNNaN7.08.0
c3.04.09.010.0
dNaNNaN11.012.0
e5.06.013.014.0
\n", "
" ], "text/plain": [ " 서울 부산 대구 광주\n", "a 1.0 2.0 NaN NaN\n", "b NaN NaN 7.0 8.0\n", "c 3.0 4.0 9.0 10.0\n", "d NaN NaN 11.0 12.0\n", "e 5.0 6.0 13.0 14.0" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pd.merge(df1, df2, how='outer', left_index=True, right_index=True)" ] }, { "cell_type": "markdown", "metadata": { "school_cell_uuid": "287c4da943664246bbdebaa20660bfa1" }, "source": [ "### join 메서드" ] }, { "cell_type": "markdown", "metadata": { "school_cell_uuid": "df6683db4e0b45e6a3a974ea5049bb9c" }, "source": [ "`merge` 명령어 대신 `join` 메서드를 사용할 수도 있다." ] }, { "cell_type": "code", "execution_count": 22, "metadata": { "school_cell_uuid": "c3b619ed36a34dd882fa95d6da27d8f8" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
서울부산대구광주
a1.02.0NaNNaN
bNaNNaN7.08.0
c3.04.09.010.0
dNaNNaN11.012.0
e5.06.013.014.0
\n", "
" ], "text/plain": [ " 서울 부산 대구 광주\n", "a 1.0 2.0 NaN NaN\n", "b NaN NaN 7.0 8.0\n", "c 3.0 4.0 9.0 10.0\n", "d NaN NaN 11.0 12.0\n", "e 5.0 6.0 13.0 14.0" ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df1.join(df2, how='outer')" ] }, { "cell_type": "markdown", "metadata": { "bootstrap": { "panel": { "class": "panel-default" } }, "school_cell_uuid": "dcc917f76597477e9aa16846fb9f36bc" }, "source": [ "````{admonition} 연습 문제 4.6.1\n", "\n", "두 개의 데이터프레임을 만들고 merge 명령으로 합친다. 단 데이터프레임은 다음 조건을 만족해야 한다.\n", "\n", "1. 각각 5 x 5 이상의 크기를 가진다.\n", "2. 공통 열을 하나 이상 가진다. 다만 공통 열의 이름은 서로 다르다.\n", "````" ] }, { "cell_type": "markdown", "metadata": { "school_cell_uuid": "a5df58b4b7a54c04baaa13015929fdad" }, "source": [ "## `concat` 함수를 사용한 데이터 연결" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "```{margin}\n", "`concat`\n", "```" ] }, { "cell_type": "markdown", "metadata": { "school_cell_uuid": "ece1c7a551c1450392fe9566465542b5" }, "source": [ "`concat` 함수를 사용하면 기준 열(key column)을 사용하지 않고 단순히 데이터를 연결(concatenate)한다.\n", "\n", "기본적으로는 위/아래로 데이터 행을 연결한다. 단순히 두 시리즈나 데이터프레임을 연결하기 때문에 인덱스 값이 중복될 수 있다. " ] }, { "cell_type": "code", "execution_count": 23, "metadata": { "school_cell_uuid": "9728e65012484a409c1b5654cf67871f" }, "outputs": [], "source": [ "s1 = pd.Series([0, 1], index=['A', 'B'])\n", "s2 = pd.Series([2, 3, 4], index=['A', 'B', 'C'])" ] }, { "cell_type": "code", "execution_count": 24, "metadata": { "school_cell_uuid": "eee3eb61c0774de088feecc6583846e3" }, "outputs": [ { "data": { "text/plain": [ "A 0\n", "B 1\n", "dtype: int64" ] }, "execution_count": 24, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s1" ] }, { "cell_type": "code", "execution_count": 25, "metadata": { "school_cell_uuid": "8fc57c638a6440ad955b7c9fab302725" }, "outputs": [ { "data": { "text/plain": [ "A 2\n", "B 3\n", "C 4\n", "dtype: int64" ] }, "execution_count": 25, "metadata": {}, "output_type": "execute_result" } ], "source": [ "s2" ] }, { "cell_type": "code", "execution_count": 26, "metadata": { "school_cell_uuid": "3fc8856b6d5740f9a80b57c0a171c323" }, "outputs": [ { "data": { "text/plain": [ "A 0\n", "B 1\n", "A 2\n", "B 3\n", "C 4\n", "dtype: int64" ] }, "execution_count": 26, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pd.concat([s1, s2])" ] }, { "cell_type": "markdown", "metadata": { "school_cell_uuid": "51015eb5b8cc4b0887f1b950b14e79eb" }, "source": [ "만약 옆으로 데이터 열을 연결하고 싶으면 `axis=1`로 인수를 설정한다." ] }, { "cell_type": "code", "execution_count": 27, "metadata": { "school_cell_uuid": "33473e4aeba0432abe750caf376d93e2" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
데이터1데이터2
a01
b23
c45
\n", "
" ], "text/plain": [ " 데이터1 데이터2\n", "a 0 1\n", "b 2 3\n", "c 4 5" ] }, "execution_count": 27, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df1 = pd.DataFrame(\n", " np.arange(6).reshape(3, 2),\n", " index=['a', 'b', 'c'],\n", " columns=['데이터1', '데이터2'])\n", "df1" ] }, { "cell_type": "code", "execution_count": 28, "metadata": { "school_cell_uuid": "eedb9d4110ac4cb99341b851d61d8605" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
데이터3데이터4
a56
c78
\n", "
" ], "text/plain": [ " 데이터3 데이터4\n", "a 5 6\n", "c 7 8" ] }, "execution_count": 28, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df2 = pd.DataFrame(\n", " 5 + np.arange(4).reshape(2, 2),\n", " index=['a', 'c'],\n", " columns=['데이터3', '데이터4'])\n", "df2" ] }, { "cell_type": "code", "execution_count": 29, "metadata": { "school_cell_uuid": "43614010ef0349a5aae59792d3bb9ca2" }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
데이터1데이터2데이터3데이터4
a015.06.0
b23NaNNaN
c457.08.0
\n", "
" ], "text/plain": [ " 데이터1 데이터2 데이터3 데이터4\n", "a 0 1 5.0 6.0\n", "b 2 3 NaN NaN\n", "c 4 5 7.0 8.0" ] }, "execution_count": 29, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pd.concat([df1, df2], axis=1)" ] }, { "cell_type": "markdown", "metadata": { "bootstrap": { "panel": { "class": "panel-default" } }, "school_cell_uuid": "6383f37855f34c88a09ee88f6ea76f75" }, "source": [ "````{admonition} 연습 문제 2\n", "\n", "어느 회사의 전반기(1월 ~ 6월) 실적을 나타내는 데이터프레임과 후반기(7월 ~ 12월) 실적을 나타내는 데이터프레임을 만든 뒤 합친다.\n", "실적 정보는 \"매출\", \"비용\", \"이익\" 으로 이루어진다. (이익 = 매출 - 비용).\n", "\n", "또한 1년간의 총 실적을 마지막 행으로 덧붙인다.\n", "````" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "celltoolbar": "Edit Metadata", "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.7.6" }, "latex_envs": { "LaTeX_envs_menu_present": true, "autoclose": false, "autocomplete": true, "bibliofile": "biblio.bib", "cite_by": "apalike", "current_citInitial": 1, "eqLabelWithNumbers": true, "eqNumInitial": 1, "hotkeys": { "equation": "Ctrl-E", "itemize": "Ctrl-I" }, "labels_anchors": false, "latex_user_defs": false, "report_style_numbering": false, "user_envs_cfg": false } }, "nbformat": 4, "nbformat_minor": 4 }